package gui.components;

import gui.WhiteBoard;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.filechooser.FileFilter;

import network.client.WhiteboardClient;
import network.server.WhiteboardServer;
import controller.DrawingController;
import data.ShapesData;
import data.WorkingMode;
import data.WorkingMode.MODE;
/**
 * The main menu bar used in the application
 * @author Jie Zhao(288654)
 *
 */
public class MainMenuBar extends JMenuBar implements Observer {
	private static final long serialVersionUID = 0L;
	private final JMenu file = new JMenu();
	private final JMenuItem menuAbout = new JMenuItem();
	private final JMenu aboutMenu = new JMenu();
	private final JMenuItem menuExit = new JMenuItem();
	private final JMenu fileMenu = new JMenu();
	private final JMenu networkMenu = new JMenu();
	private final JMenuItem menuConnect = new JMenuItem();
	private final JMenuItem menuHost = new JMenuItem();
	private final JMenuItem menuNew = new JMenuItem();
	private final JMenuItem menuOpen = new JMenuItem();
	private final JMenuItem menuSave = new JMenuItem();
	private final JMenuItem menuSaveas = new JMenuItem();
	private final JMenuItem menuLeave = new JMenuItem();
	private ConnectDialog connectDialog = null;
	private HostDialog hostDialog = null;
	private final WorkingMode wm = WorkingMode.getInstance();

	private WhiteBoard parent = null;
	private WhiteboardCanvas canvas = null;

	@Override
	public void update(Observable o, Object arg) {
		switch (wm.getWorkingMode()) {
		case SERVER:
			menuNew.setEnabled(true);
			menuOpen.setEnabled(true);
			menuSave.setEnabled(true);
			menuSaveas.setEnabled(true);
			menuLeave.setEnabled(false);
			menuHost.setEnabled(false);
			menuConnect.setEnabled(false);
			break;
		case CLIENT:
			menuNew.setEnabled(false);
			menuOpen.setEnabled(false);
			menuSave.setEnabled(false);
			menuSaveas.setEnabled(false);
			menuLeave.setEnabled(true);
			menuHost.setEnabled(false);
			menuConnect.setEnabled(false);
			break;
		case LOCAL:
			menuNew.setEnabled(true);
			menuOpen.setEnabled(true);
			menuSave.setEnabled(true);
			menuSaveas.setEnabled(true);
			menuLeave.setEnabled(false);
			menuHost.setEnabled(true);
			menuConnect.setEnabled(true);
			break;
		default:
			break;
		}
	}

	public MainMenuBar(WhiteBoard wb, WhiteboardCanvas wc) {
		wm.addObserver(this);
		this.parent = wb;
		this.canvas = wc;

		fileMenu.setText("File");
		this.add(file);
		file.setText("File");

		file.add(menuNew);
		menuNew.addActionListener(new MenuNewActionListener());
		menuNew.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
				InputEvent.ALT_MASK));
		menuNew.setText("New");

		file.add(menuOpen);
		menuOpen.addActionListener(new MenuOpenActionListener());
		menuOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
				InputEvent.ALT_MASK));
		menuOpen.setText("Open");

		file.add(menuSave);
		menuSave.addActionListener(new MenuSaveActionListener());
		menuSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
				InputEvent.CTRL_MASK));
		menuSave.setText("Save");

		file.add(menuSaveas);
		menuSaveas.addActionListener(new MenuSaveasActionListener());
		menuSaveas.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
				InputEvent.ALT_MASK));
		menuSaveas.setText("Save As...");

		file.add(menuExit);
		menuExit.addActionListener(new MenuExitActionListener());
		menuExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E,
				InputEvent.ALT_MASK));
		menuExit.setText("Exit");

		this.add(networkMenu);
		networkMenu.setText("Network");

		networkMenu.add(menuHost);
		menuHost.addActionListener(new MenuHostActionListener());
		menuHost.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H,
				InputEvent.ALT_MASK));
		menuHost.setText("Host...");

		networkMenu.add(menuConnect);
		menuConnect.addActionListener(new MenuConnectActionListener());
		menuConnect.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
				InputEvent.ALT_MASK));
		menuConnect.setText("Connect...");

		networkMenu.add(menuLeave);
		menuLeave.addActionListener(new MenuLeaveActionListener());
		menuLeave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L,
				InputEvent.ALT_MASK));
		menuLeave.setText("Leave");

		this.add(aboutMenu);
		aboutMenu.setText("About");

		aboutMenu.add(menuAbout);
		menuAbout.addActionListener(new MenuAboutActionListener());
		menuAbout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,
				InputEvent.ALT_MASK));
		menuAbout.setText("About");
	}

	protected void menuHost_actionPerformed(ActionEvent e) {
		if (hostDialog == null) {
			hostDialog = new HostDialog();
		}
		hostDialog.setVisible(true);
		int returnVal = hostDialog.getReturnvalue();
		if (returnVal == 0) {
			server = hostDialog.getServer();
			wm.changeWorkingMode(MODE.SERVER);
		} else {
			wm.changeWorkingMode(MODE.LOCAL);
		}

	}

	WhiteboardClient client = null;

	protected void menuConnect_actionPerformed(ActionEvent e) {
		if (connectDialog == null) {
			connectDialog = new ConnectDialog();
		}
		connectDialog.setVisible(true);
		int returnVal = connectDialog.getReturnvalue();
		if (returnVal == 0) {
			client = connectDialog.getClient();
			wm.changeWorkingMode(MODE.CLIENT);
		} else {
			wm.changeWorkingMode(MODE.LOCAL);
		}

		// WhiteboardClient.connect(serverAddress, Integer.parseInt(port));
	}

	WhiteboardServer server = null;

	private class MenuLeaveActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			switch (wm.getWorkingMode()) {
			case CLIENT:
				client.close();
				break;
			case SERVER:
				server.close();
				break;
			default:
				break;
			}
			wm.changeWorkingMode(MODE.LOCAL);
		}
		
	}

	private class MenuHostActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			menuHost_actionPerformed(e);
		}
	}

	private class MenuConnectActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			menuConnect_actionPerformed(e);
		}
	}

	private class MenuSaveActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			JFileChooser jfc = new JFileChooser();
			jfc.setFileFilter(dwbFileFilter);
			jfc.setAcceptAllFileFilterUsed(false);
			jfc.setMultiSelectionEnabled(false);
			int result = jfc.showSaveDialog(null);
			if (result != JFileChooser.APPROVE_OPTION) {
				return;
			}
			ShapesData.getInstance().save(jfc.getSelectedFile());
			canvas.repaint();

		}
	}

	private class MenuExitActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			parent.dispose();
			System.exit(0);
		}
	}

	private class MenuSaveasActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			JFileChooser jfc = new JFileChooser();
			jfc.setFileFilter(imgFileFilter);
			jfc.setAcceptAllFileFilterUsed(false);
			jfc.setMultiSelectionEnabled(false);
			int result = jfc.showSaveDialog(null);
			if (result != JFileChooser.APPROVE_OPTION) {
				return;
			}
			String filename = jfc.getSelectedFile().getName();
			canvas.saveToImage(jfc.getSelectedFile());

		}
	}

	private class MenuNewActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			DrawingController.getInstance().clear();
			canvas.repaint();
		}
	}

	private class MenuOpenActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			JFileChooser jfc = new JFileChooser();
			jfc.setFileFilter(dwbFileFilter);
			jfc.setAcceptAllFileFilterUsed(false);
			jfc.setMultiSelectionEnabled(false);
			int result = jfc.showOpenDialog(null);
			if (result != JFileChooser.APPROVE_OPTION) {
				return;
			}
			ShapesData.getInstance().load(jfc.getSelectedFile());
			canvas.repaint();
		}
	}
	private class MenuAboutActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			menuAbout_actionPerformed(e);
		}
	}


	final FileFilter dwbFileFilter = new FileFilter() {
		public boolean accept(File pathname) {
			if (pathname.getName().endsWith(".dwb")) {
				return true;
			}
			if (pathname.isDirectory()) {
				return true;
			}
			return false;
		}

		public String getDescription() {
			return "Distributed White Board File";
		};
	};
	final FileFilter imgFileFilter = new FileFilter() {
		@Override
		public boolean accept(File f) {
			if (f.isDirectory()) {
				return true;
			}
			if (f.getName().endsWith(".png") || f.getName().endsWith(".jpg")) {
				return true;
			}
			return false;
		}

		@Override
		public String getDescription() {
			return "Image File";
		}
	};
	protected void menuAbout_actionPerformed(ActionEvent e) {
		new AboutDialog().setVisible(true);
	}

}
